﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;

namespace Truncation.Detector.Windows
{
    public class ResourceData
    {
        private readonly string _folder;
        private readonly string _resxName;
        private readonly string _nameSpace;
        private readonly Dictionary<string, string> _nativeTable = new Dictionary<string, string>();
        private readonly Dictionary<string, Dictionary<string, string>> _languageTable = new Dictionary<string, Dictionary<string, string>>();
        
        //public ResourceReader(string fileName)
        //{
        //    _folder = Path.GetDirectoryName(fileName);
        //    _resxName = Path.GetFileNameWithoutExtension(fileName);
        //    _baseFile = fileName;

        //    ReadAll();
        //}

        public ResourceData(IEnumerable<ResxFile> resxFiles)
        {
            var sortedResx = resxFiles.OrderBy(s => s.Lang);
            var resxFile = sortedResx.First();
            _nameSpace = Path.GetDirectoryName(resxFile.FileName).Replace('\\', '.');
            string fullPath = Path.Combine(resxFile.Folder, resxFile.FileName);
            _folder = Path.GetDirectoryName(fullPath);
            _resxName = Path.GetFileNameWithoutExtension(fullPath);
            if (_folder == null || !File.Exists(fullPath))
                throw new Exception(String.Format("Path: {0} not exist", fullPath));
            var ret = ReadResxFile(fullPath, _nativeTable);
            if (!ret)
                return;
            foreach (var file in sortedResx.SkipWhile(s => String.IsNullOrEmpty(s.Lang)))
            {
                var language = Translation.LangCodesConvert(file.Lang);
                var path = Path.Combine(_folder, _resxName) + "." + file.Lang + ".resx";
                if (!File.Exists(path))
                {
                    throw new Exception(String.Format("Path: {0} not exist", path));
                }
                if (String.IsNullOrEmpty(language))
                {
                    throw new Exception(String.Format("the language: {0} is not valid", path));
                }
                var resourceMap = new Dictionary<string, string>();
                ReadResxFile(path, resourceMap);
                _languageTable.Add(language, resourceMap);
            }
        }

        //private void ReadAll()
        //{
        //    //DE, ES, FR, JA, SC
        //    var ret = ReadResxFile(_baseFile, _nativeTable);
        //    if (!ret)
        //        return;
        //    var directoryInfo = new DirectoryInfo(_folder);
        //    string pattern = _resxName + ".*.resx";
        //    var files = directoryInfo.EnumerateFiles(pattern, SearchOption.TopDirectoryOnly);
        //    foreach (FileInfo file in files)
        //    {
        //        if (file.Name.ToLowerInvariant().Contains(_resxName.ToLowerInvariant() + ".resx"))
        //        {
        //            continue;
        //        }
        //        string language = file.Name.Substring(_resxName.Length + 1).Replace(".resx", String.Empty);
        //        language = Translation.LangCodesConvert(language);
        //        if (String.IsNullOrEmpty(language))
        //        {
        //            throw new Exception(String.Format("the language: {0} is not valid", file.FullName));
        //        }
        //        var resourceMap = new Dictionary<string, string>();
        //        ReadResxFile(file.FullName, resourceMap);
        //        _languageTable.Add(language, resourceMap);
        //    }
        //}

        private bool ReadResxFile(string path, Dictionary<string, string> resourceMap)
        {
            int orig = resourceMap.Count;
            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = new XmlTextReader(stream))
            {
                var doc = new XmlDocument();
                doc.Load(reader);
                var datas = doc.SelectNodes("/root/data");
                if (datas == null)
                    return false;
                foreach (var node in datas.Cast<XmlElement>().Where(x => x.HasAttribute("xml:space") && x.Attributes["xml:space"].Value == "preserve"))
                {
                    var value = node.SelectSingleNode("value");
                    var name = node.Attributes["name"].Value;
                    if (value == null || String.IsNullOrEmpty(name))
                        continue;
                    resourceMap.Add(name, value.InnerText);
                }
            }
            return resourceMap.Count > orig;
        }

        public bool IsEmpty { get { return !_nativeTable.Any(); } }
        
        public string ResxName { get { return _resxName; } }

        public string ResxFolder { get { return _folder; } }
       
        public ICollection<string> SupportLangs
        {
            get { return _languageTable.Keys; }
        }

        public string NameSpace
        {
            get { return _nameSpace; }
        }

        public string GetValue(string key, string lang)
        {
            string value;
            if (!_nativeTable.TryGetValue(key, out value))
                return String.Empty;
            if (_languageTable.ContainsKey(lang))
            {
                _languageTable[lang].TryGetValue(key, out value);
            }
            else if (!String.IsNullOrEmpty(value))
            {
                value = Translation.Translate(value, lang);
            }
            return value;
        }
    }
}
